package com.example.waterdispenserm2.mo.water;

// Hob2DisplayBoard.java - 串口通信工具类
import android.util.Log;

import com.aill.androidserialport.SerialPort;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;


    public class Hob2DisplayBoard {
        private static final String TAG = "Hob2DisplayBoard";
        private static final byte IDENTIFICATION_CODE = (byte) 0xA5;
        private static final int PACKET_LENGTH = 7; // 主机数据包长度

        private SerialPort mSerialPort;
        private InputStream mInputStream;
        private OutputStream mOutputStream;
        private Thread mReadThread;
        private DisplayCallback mCallback;
        private boolean isRunning = false;

        // 按键定义
        public static final int KEY_NONE = 0;
        public static final int KEY_POWER = 1;
        public static final int KEY_TIMER = 2;
        public static final int KEY_DEC = 3;
        public static final int KEY_INC = 4;
        public static final int KEY_FUNCTION = 5;
        public static final int KEY_START = 6;

        // LED功能位定义
        public static final int LED_FRYING = 7;
        public static final int LED_PORRIDGE = 6;
        public static final int LED_HOTPOT = 5;
        public static final int LED_HIGH_FIRE = 4;
        public static final int LED_LOW_FIRE = 3;
        public static final int LED_WATER = 2;
        public static final int LED_STEAM = 1;
        public static final int LED_SOUP = 0;

        private int mLastKeyCode = KEY_NONE; // 记录上一次发送的按键

        public interface DisplayCallback {
            void onDisplayUpdate(byte[] digitSegments, byte ledStatus);
            void onDataError(String message);
            void logMessage(String message);
        }

        /**
         * 初始化串口
         * @param device 串口设备路径 (e.g. /dev/ttyS1)
         * @param baudrate 波特率 (e.g. 9600)
         * @param callback 数据回调接口
         */
        public void init(String device, int baudrate, DisplayCallback callback) {
            try {
                mSerialPort = new SerialPort(new File(device), baudrate, 0);
                mInputStream = mSerialPort.getInputStream();
                mOutputStream = mSerialPort.getOutputStream();
                mCallback = callback;
                startReading();
                logMessage("串口初始化成功: " + device + "@" + baudrate);
            } catch (IOException e) {
                Log.e(TAG, "Error initializing serial port", e);
                logMessage("串口初始化失败: " + e.getMessage());
                if (mCallback != null) {
                    mCallback.onDataError("串口初始化失败: " + e.getMessage());
                }
            }
        }

        private void startReading() {
            isRunning = true;
            mReadThread = new Thread(() -> {
                byte[] buffer = new byte[1024];
                int bytesRead;

                while (isRunning && !Thread.interrupted()) {
                    try {
                        if (mInputStream.available() >= PACKET_LENGTH) {
                            bytesRead = mInputStream.read(buffer, 0, PACKET_LENGTH);
                            if (bytesRead == PACKET_LENGTH) {
                                processPacket(Arrays.copyOf(buffer, PACKET_LENGTH));
                            }
                        }
                        Thread.sleep(1); // 避免CPU占用过高
                    } catch (IOException | InterruptedException e) {
                        Log.e(TAG, "Serial read error", e);
                        logMessage("串口读取错误: " + e.getMessage());
                    }
                }
            });
            mReadThread.start();
        }

        private void processPacket(byte[] packet) {
            logMessage("收到原始数据包: " + formatByteArray(packet));

            // 验证识别码
            if (packet[0] != IDENTIFICATION_CODE) {
                String error = "无效识别码: " + formatByte(packet[0]) + " (期望: 0xA5)";
                logMessage(error);
                if (mCallback != null) {
                    mCallback.onDataError(error);
                }
                return;
            }

            // 计算校验和
            byte checksum = 0;
            for (int i = 0; i < PACKET_LENGTH - 1; i++) {
                checksum += packet[i];
            }

            // 验证校验和
            if (checksum != packet[PACKET_LENGTH - 1]) {
                String error = "校验和错误: 计算值=" + formatByte(checksum) +
                        ", 接收值=" + formatByte(packet[PACKET_LENGTH - 1]);
                logMessage(error);
                if (mCallback != null) {
                    mCallback.onDataError(error);
                }
                return;
            }

            logMessage("数据包验证通过");

            // 提取显示数据
            byte[] digitSegments = Arrays.copyOfRange(packet, 1, 5); // 4位数码管
            byte ledStatus = packet[5]; // LED状态

            // 更新UI
            if (mCallback != null) {
                mCallback.onDisplayUpdate(digitSegments, ledStatus);
            }

            // 延时4ms后发送回复 (协议要求)
            try {
                Thread.sleep(4);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        /**
         * 发送按键事件（按下时调用）
         * @param keyCode 按键代码
         */
        public void sendKeyEvent(int keyCode) {
            // 避免重复发送相同按键
            if (keyCode == mLastKeyCode) {
                logMessage("忽略重复按键: " + getKeyName(keyCode));
                return;
            }

            // 先发送释放上一次按键（如果有）
            if (mLastKeyCode != KEY_NONE) {
                sendKeyPacket(KEY_NONE);
            }

            // 发送当前按键
            sendKeyPacket(keyCode);
            mLastKeyCode = keyCode;
        }

        /**
         * 发送按键释放事件
         */
        public void sendKeyRelease() {
            if (mLastKeyCode != KEY_NONE) {
                sendKeyPacket(KEY_NONE);
                mLastKeyCode = KEY_NONE;
            }
        }

        // 实际发送按键数据包
        private void sendKeyPacket(int keyCode) {
            if (mOutputStream == null) {
                logMessage("输出流未初始化，无法发送按键");
                return;
            }

            byte[] packet = new byte[3];
            packet[0] = (byte)0x00; // 引导码 (实际硬件需要2ms低电平)
            packet[1] = (byte) keyCode;
            packet[2] = (byte) ~packet[1]; // 校验码 = 数据码取反

            try {
                mOutputStream.write(packet);
                mOutputStream.flush();

                // 记录日志
                String action = (keyCode == KEY_NONE) ? "释放" : "按下";
                logMessage("发送按键: " + action + " " + getKeyName(keyCode) +
                        " (0x" + Integer.toHexString(keyCode) + ")");
            } catch (IOException e) {
                Log.e(TAG, "Error sending key event", e);
                logMessage("发送按键失败: " + e.getMessage());
                if (mCallback != null) {
                    mCallback.onDataError("发送按键失败: " + e.getMessage());
                }
            }
        }

        // 获取按键名称
        private String getKeyName(int keyCode) {
            switch (keyCode) {
                case KEY_POWER: return "电源";
                case KEY_TIMER: return "定时";
                case KEY_DEC: return "减";
                case KEY_INC: return "加";
                case KEY_FUNCTION: return "功能";
                case KEY_START: return "启动";
                case KEY_NONE: return "无按键";
                default: return "未知按键";
            }
        }

        /**
         * 关闭串口释放资源
         */
        public void close() {
            isRunning = false;
            sendKeyRelease(); // 确保释放所有按键

            if (mReadThread != null) {
                mReadThread.interrupt();
            }
            try {
                if (mInputStream != null) mInputStream.close();
                if (mOutputStream != null) mOutputStream.close();
                if (mSerialPort != null) mSerialPort.close();
                logMessage("串口资源已释放");
            } catch (IOException e) {
                Log.e(TAG, "Error closing resources", e);
                logMessage("释放串口资源失败: " + e.getMessage());
            }
        }

        // 日志记录方法
        private void logMessage(String message) {
            if (mCallback != null) {
                mCallback.logMessage(message);
            }
        }

        // 格式化字节数组为十六进制字符串
        private String formatByteArray(byte[] bytes) {
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) {
                sb.append(String.format("%02X ", b));
            }
            return sb.toString().trim();
        }

        // 格式化单个字节为十六进制字符串
        private String formatByte(byte b) {
            return String.format("0x%02X", b);
        }

        // 数码管段码转换工具方法
        public static String segmentToDigit(byte segment) {
            switch (segment) {
                case 0x3F: return "0";
                case 0x06: return "1";
                case 0x5B: return "2";
                case 0x4F: return "3";
                case 0x66: return "4";
                case 0x6D: return "5";
                case 0x7D: return "6";
                case 0x07: return "7";
                case 0x7F: return "8";
                case 0x6F: return "9";
                case 0x77: return "A";
                case 0x7C: return "B";
                case 0x39: return "C";
                case 0x5E: return "D";
                case 0x79: return "E";
                case 0x71: return "F";
                case 0x00: return " ";
                case 0x40: return "-"; // 负号
                case 0x63: return "°"; // 温度符号
                case 0x73: return "P"; // 功率
                case 0x50: return "r"; // 预约
                default: return "?"; // 未知符号
            }
        }


}
